#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    scene = new QGraphicsScene();
    scale = new qreal();
    *scale = 1;

    ui->graphicsView->setScene(scene);
    scene->setSceneRect(-100000,-100000,200000,200000);
    scene->setBackgroundBrush(Qt::black);

    ui->radioButton->setChecked(true);
    ui->radioButton_2->setChecked(true);
    showLabels = true;

    data = new Data();

    visible = true;
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_actionZoom_in_triggered()
{
    if(*scale > 1000)
        return;

    *scale = *scale*1.25;
    ui->graphicsView->scale(1.25,1.25);
}

void MainWindow::on_actionZoom_out_triggered()
{
    if(*scale < 0.10)
        return;

    *scale = *scale*0.8;
    ui->graphicsView->scale(0.8,0.8);
}

void MainWindow::on_actionOpen_Netlist_triggered()
{
    if(rulesMap == 0)
    {
        ui->plainTextEdit->appendHtml("<font color='red'>Please open a .rul file.</font>");
        return;
    }
    QString fileName = QFileDialog::getOpenFileName(this, tr("Open Spice File"), QDir::currentPath(), tr("Spice File (*.sp)"));

    if(fileName.isNull())
        return;

    ui->plainTextEdit->appendHtml("<font color='green'>Openning: " + fileName + "</font>");

    data->readSpiceFile(fileName, ui->plainTextEdit);
    data->setScale(scale);

    ui->listWidget->clear();

    foreach(Cell* c, *(data->cells))
       ui->listWidget->addItem(c->getCellName());
}

void MainWindow::on_listWidget_itemClicked(QListWidgetItem *item)
{
    if(ui->listWidget->selectedItems().empty())
        return;

    ui->listWidget_2->clear();
    ui->listWidget_3->clear();
    ui->listWidget_4->clear();

    Cell* cell = data->cells->at(ui->listWidget->currentRow());

    foreach(Transistor *t, *(cell->nTransistors))
        ui->listWidget_2->addItem(t->transistorName + "(" + t->transistorType + ")");

    foreach(Transistor *t, *(cell->pTransistors))
        ui->listWidget_2->addItem(t->transistorName + "(" + t->transistorType + ")");

    foreach(QString pin, cell->pins)
        ui->listWidget_3->addItem(pin);

    //GND
    ui->doubleSpinBox->setValue(cell->gndHeight/factor);
    //VDD
    ui->doubleSpinBox_2->setValue(cell->vccHeight/factor);
    //PMOS
    ui->doubleSpinBox_3->setValue(cell->pmosHeight/factor);
    //NMOS
    ui->doubleSpinBox_4->setValue(cell->nmosHeight/factor);
}

void MainWindow::on_actionPositioning_triggered()
{
    if(data->cells->empty() || ui->listWidget->selectedItems().empty())
        return;

    int alg = ui->radioButton->isChecked() ? 1 : ui->radioButton_3->isChecked() ? 2 : 3;

    if(alg == 1)
        ui->plainTextEdit->appendHtml("<font color='blue'>Spice Sequence Placemente started...Selected Cell: " + ui->listWidget->selectedItems().first()->text() +  "</font>");
    else if(alg == 2)
        ui->plainTextEdit->appendHtml("<font color='blue'>PBS placement started...Selected Cell: " + ui->listWidget->selectedItems().first()->text() +  "</font>");
    else
        ui->plainTextEdit->appendHtml("<font color='blue'>TA placement started...Selected Cell: " + ui->listWidget->selectedItems().first()->text() +  "</font>");

    Placement p;
    p.placeTransistors(data->cells->at(ui->listWidget->currentRow()),alg,ui->plainTextEdit);

    if(alg == 1)
        ui->plainTextEdit->appendHtml("<font color='blue'>Spice Sequence finished!</font>");
    else if(alg == 2)
        ui->plainTextEdit->appendHtml("<font color='blue'>PBS placement finished!</font>");
    else
        ui->plainTextEdit->appendHtml("<font color='blue'>TA placement finished!</font>");

    this->on_actionDraw_Cell_triggered();
}

void MainWindow::on_actionDraw_Cell_triggered()
{
    if(data->cells->empty() || ui->listWidget->selectedItems().empty())
        return;

    foreach(QGraphicsItem *item, scene->items())
        scene->removeItem(item);

    Cell* cell = data->cells->at(ui->listWidget->currentRow());
    cell->refreshScenePositions();
    cell->addItemsToScene(scene);

    ui->label_11->setText("Cell Size: " + cell->getCellSize());

    this->on_actionFit_in_View_triggered();
}

void MainWindow::on_listWidget_2_itemClicked(QListWidgetItem *item)
{
    if(ui->listWidget->selectedItems().empty())
        return;

    ui->listWidget_4->clear();
    Transistor* t;
    int nNmos = data->cells->at(ui->listWidget->currentRow())->nTransistors->size();

    if(ui->listWidget_2->currentRow() <  nNmos)
        t = data->cells->at(ui->listWidget->currentRow())->nTransistors->at(ui->listWidget_2->currentRow());
    else
        t = data->cells->at(ui->listWidget->currentRow())->pTransistors->at(ui->listWidget_2->currentRow() - nNmos);

    ui->listWidget_4->addItem(t->sourceNetName);
    ui->listWidget_4->addItem(t->gateNetName);
    ui->listWidget_4->addItem(t->drainNetName);
    ui->listWidget_4->addItem(t->bulkNetName);
}

void MainWindow::on_doubleSpinBox_valueChanged(double arg1)
{
    if(arg1 + 0.0001 < (((Rules::getRule("NP.E.1") + Rules::getRule("CO.E.1"))*2) + Rules::getRule("CO.W.1"))/factor)
        return;

    if(!data->cells->empty())
        data->cells->at(ui->listWidget->currentRow())->gndHeight = arg1*factor;
}

void MainWindow::on_doubleSpinBox_2_valueChanged(double arg1)
{
    if(arg1 + 0.0001< (((Rules::getRule("NP.E.1") + Rules::getRule("CO.E.1"))*2) + Rules::getRule("CO.W.1"))/factor)
        return;

    if(!data->cells->empty())
        data->cells->at(ui->listWidget->currentRow())->vccHeight = arg1*factor;
}

void MainWindow::on_doubleSpinBox_3_valueChanged(double arg1)
{
    if(!data->cells->empty())
        data->cells->at(ui->listWidget->currentRow())->pmosHeight = arg1*factor;
}

void MainWindow::on_doubleSpinBox_4_valueChanged(double arg1)
{
    if(!data->cells->empty())
        data->cells->at(ui->listWidget->currentRow())->nmosHeight = arg1*factor;
}

void MainWindow::on_actionExit_triggered()
{
    this->close();
}

void MainWindow::on_actionFit_in_View_triggered()
{
    if(data->cells->empty() || ui->listWidget->selectedItems().empty())
        return;

    Cell* cell = data->cells->at(ui->listWidget->currentRow());

    QPointF topLeft = cell->vccRectItem->boundingRect().topLeft();
    topLeft.setY(topLeft.y() -(Rules::getRule("OD.C.4") - Rules::getRule("NP.E.1")));
    QPointF bottomRight = cell->gndRectItem->boundingRect().bottomRight();

    QRectF view(cell->vccRectItem->mapToScene(topLeft),cell->gndRectItem->mapToScene(bottomRight));

    ui->graphicsView->fitInView(view,Qt::KeepAspectRatio);

    *scale = ui->graphicsView->transform().m11();
}

void MainWindow::on_actionShow_Only_Cell_triggered(bool checked)
{
    int tabSize = 0;

    if(!checked)
        tabSize = 80;

    QList<int> size;
    size.append(tabSize);
    size.append(ui->splitter_2->maximumHeight()-tabSize);
    ui->splitter_2->setSizes(size);

    size.clear();
    size.append(ui->splitter_3->maximumHeight()-tabSize);
    size.append(tabSize);
    ui->splitter_3->setSizes(size);

    this->on_actionFit_in_View_triggered();
}

void MainWindow::on_actionRouting_triggered()
{
    if(data->cells->empty() || ui->listWidget->selectedItems().empty())
        return;

    ui->plainTextEdit->appendHtml("<font color='blue'>Routing started...Selected Cell: " + ui->listWidget->selectedItems().first()->text() +  "</font>");

    data->cells->at(ui->listWidget->currentRow())->refreshScenePositions();

    int alg = ui->radioButton_2->isChecked() ? 1 : 2;

    Routing r;
    r.routeTransistors(data->cells->at(ui->listWidget->currentRow()),alg,ui->plainTextEdit);

    data->setScale(scale);

    ui->plainTextEdit->appendHtml("<font color='blue'>Routing finished!</font>");

    QString fail = data->cells->at(ui->listWidget->currentRow())->removeOutSideRoutedM1();

    if(fail.size() != 0)
    {
        QMessageBox::warning(this,"Routing Fail", "The following networks were not routed: " + fail );
    }

    this->on_actionDraw_Cell_triggered();
}

void MainWindow::on_actionShow_Net_Labels_triggered()
{
    showLabels = !showLabels;

    foreach(Cell* cell, *(data->cells))
        cell->setShowLabel(showLabels);

    this->on_actionDraw_Cell_triggered();
}

void MainWindow::on_actionShow_Pins_triggered()
{

    if(data->cells->empty() || ui->listWidget->selectedItems().empty())
        return;

    Cell* cell = data->cells->at(ui->listWidget->currentRow());


    visible = !visible;

    foreach(QGraphicsItem* item, scene->items())
        item->setVisible(visible);

    foreach(Metal* item, *(cell->m1Items))
        if(item->bottomRight.x() == 10 && item->bottomRight.y() == 10)
            item->setVisible(true);
}

void MainWindow::on_actionCIF_File_triggered()
{
    if(data->cells->empty() || ui->listWidget->selectedItems().empty())
        return;

    QString fileName = QFileDialog::getSaveFileName(this, tr("Save CIF File"), QDir::currentPath(), tr("CIF File (*.cif)"));

    if(fileName.isNull())
        return;

    Cell* cell = data->cells->at(ui->listWidget->currentRow());
    ui->plainTextEdit->appendHtml("<font color='green'>Exporting: " + cell->cellName + "</font>");

    cell->exportAsCif(fileName);
}

void MainWindow::on_actionReduce_Polygons_triggered()
{
    if(data->cells->empty() || ui->listWidget->selectedItems().empty())
        return;

    Cell* cell = data->cells->at(ui->listWidget->currentRow());
   // cell->reducePolygons();
}

void MainWindow::on_actionOpen_Rules_File_triggered()
{
    QString fileName = QFileDialog::getOpenFileName(this, tr("Open Rules File"), QDir::currentPath(), tr("Rules File (*.rul)"));

    if(fileName.isNull())
        return;

    ui->plainTextEdit->appendHtml("<font color='green'>Openning: " + fileName + "</font>");
    Rules::openRulesFile(fileName, ui->plainTextEdit);
}
